#pragma once

#include "DAEFloat3.h"
#include "LineSegment.h"
#include "OBB.h"

/**
* Contains the definition of a Cone object.
* @author Koen Samyn
*/ 
class Cone
{
public:
	/**
	* Creates a new cone, with an origin, axis, and angle.
	* @param origin the origin of the cone.
	* @param axis the axis of the cone.
	* @param angle the angle of the cone.
	* @param the start distance of the cone.
	* @param the stop distance of the cone.
	*/
	Cone(DAEFloat3 origin, DAEFloat3 axis, float angle, float startRange, float stopRange);
	/**
	* Deletes the cone object.
	*/
	virtual ~Cone(void);

	/**
	* Gives a distance (in radians) of the provided point to the  cone.
	* @param p1 the point to test.
	* @return the distance in radians of the provided point to the cone.
	*/
	float TestPoint(DAEFloat3& p1);

	/**
	* Checks if the given point is inside the cone.
	* @param p the point to check.
	* @return true if the point is inside , false otherwise.
	*/
	bool IsInside(DAEFloat3& p);
	/**
	* Checks if a line segment intersects.
	* @param lineSegment the line segment to check.
	* @return true if the line segment intersects , false otherwise.
	*/
	bool IntersectsLine(LineSegment& line);
	/**
	* Checks if a line segment defined by p1 and p2 intersects this cone..
	* @param lineSegment the line segment to check.
	* @return true if the line segment intersects , false otherwise.
	*/
	bool IntersectsLine(DAEFloat3& p1, DAEFloat3& p2);
	/**
	* Checks if this cone intersects the triangle defined by the points p1, p2 and p3.
	* @return true if the triangle is intersected by the cone , false otherwise.
	*/
	bool IntersectsTriangle( DAEFloat3& p1, DAEFloat3& p2, DAEFloat3& p3);
	/**
	* Checks if this cone intersects the triangle defined by the points p1, p2 and p3.
	* @return true if the triangle is intersected by the cone , false otherwise.
	*/
	bool IntersectsTriangle2( DAEFloat3& p1, DAEFloat3& p2, DAEFloat3& p3);

	/**
	* Checks if this cone intersects the quad defined by the points p1, p2 , p3 and p4.
	* @return true if the quad is intersected by the cone , false otherwise.
	*/
	bool IntersectsQuad( DAEFloat3& p1, DAEFloat3& p2, DAEFloat3& p3, DAEFloat3& p4);
	/**
	* Checks if the obb object intersects this cone. This function will split the
	* obb into triangles.
	* @return true if the obb mesh intersects this cone, false otherwise.
	*/
	bool IntersectsOBB( OBB& obb );

	/**
	* Intersect the line with the cone and return the intersection points.
	* @param p1 the first point of the line.
	* @param p2 the second point of the line.
	* @param ip1 the first intersection point result.
	* @param ip2 the second intersection point result.
	* @return the number of intersection points.
	*/
	int IntersectLine( DAEFloat3& p1, DAEFloat3& p2, DAEFloat3& ip1, DAEFloat3& ip2);
	/**
	* This is basicly the same method as the IntersectLine that returns the intersection
	* points but this version just returns the t values , where t is defined as :
	* ip = p0 + t*(p1-p0)
	* @param p1 the first point of the line.
	* @param p2 the second point of the line.
	* @param t1 the first interpolation value.
	* @param t2 the second interpolation value.
	* @param limitTs limit the t values to fall between 0 and 1
	* @return the number of intersection points.
	*/
	int IntersectLine( DAEFloat3& p1, DAEFloat3& p2, float& t1, float& t2, bool limitTs=true);
	/**
	* Checks if the axis of this cone intersects plane of the triangle inside the
	* triangle. The results are returned in barycentric coordinates.
	* @param p1 the first point of the triangle.
	* @param p2 the second point of the triangle.
	* @param p3 the third point of the triangle.
	* @param l1 the first barycentric coordinate as out parameter.
	* @param l2 the second barycentric coordinate as out parameter.
	*/
	bool IntersectTriangle( DAEFloat3& p1, DAEFloat3& p2, DAEFloat3& p3, float& l1, float& l2);
	/**
	*  Intersects the axis of this cone with the given plane.
	* @param result the result of the intersection
	* @param origin the origin of the plane.
	* @param normal the normal of the plane. 
	* @param true if the axis intersects the plane , false otherwise.
	*/
	bool AxisIntersectPlane(DAEFloat3& result, DAEFloat3& origin, DAEFloat3& normal);
private:

	DAEFloat3 m_Origin;
	DAEFloat3 m_Axis;
	float m_Angle;
	/**
	* the cosinus of m_Angle squared.
	*/
	float m_CosAngle2;

	float m_StartRange;
	float m_StopRange;

	bool AxisIntersectsTriangle(DAEFloat3& p1, DAEFloat3& p2, DAEFloat3& p3);

	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Cone(const Cone& t);
	Cone& operator=(const Cone& t);
};

